package com.itaem.community.modules.infrastructure.company.department.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itaem.community.core.entity.Entity;
import com.itaem.community.core.exception.data.DataAlreadyExistsException;
import com.itaem.community.core.exception.data.DataSaveException;
import com.itaem.community.core.exception.data.FailOperationException;
import com.itaem.community.core.exception.data.NoSuchDataException;
import com.itaem.community.modules.infrastructure.company.company.entity.PropertyManagementCompanyEntity;
import com.itaem.community.modules.infrastructure.company.company.mapper.PropertyManagementCompanyDAO;
import com.itaem.community.modules.infrastructure.company.department.dto.*;
import com.itaem.community.modules.infrastructure.company.department.entity.DepartmentEntity;
import com.itaem.community.modules.infrastructure.company.department.entity.WorkerEntity;
import com.itaem.community.modules.infrastructure.company.department.mapper.DepartmentDAO;
import com.itaem.community.modules.infrastructure.company.department.mapper.DepartmentTransformer;
import com.itaem.community.modules.infrastructure.company.department.mapper.WorkerDAO;
import com.itaem.community.modules.infrastructure.company.department.mapper.WorkerTransformer;
import com.itaem.community.modules.infrastructure.company.department.service.DepartmentService;
import com.itaem.community.modules.infrastructure.user.entity.UserEntity;
import com.itaem.community.modules.infrastructure.user.mapper.UserDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;
import java.util.stream.Collectors;

/**
 * <p>
 * 物业部门 服务实现类
 * </p>
 *
 * @author tomato
 * @since 2020-10-28
 */
@Service
public class DepartmentServiceImpl extends ServiceImpl<DepartmentDAO, DepartmentEntity> implements DepartmentService {

    @Autowired
    private PropertyManagementCompanyDAO propertyManagementCompanyDAO;

    @Autowired
    private DepartmentDAO departmentDAO;

    @Autowired
    private DepartmentTransformer departmentTransformer;

    @Autowired
    private WorkerDAO workerDAO;

    @Autowired
    private WorkerTransformer workerTransformer;

    @Autowired
    private UserDAO userDAO;

    @Override
    public Boolean saveDepartment(DepartmentCreateDTO createDto) {
        // 确认是否存在指定的物业公司
        if (propertyManagementCompanyDAO.selectCount(
                new QueryWrapper<PropertyManagementCompanyEntity>()
                        .lambda()
                        .eq(Entity::getId, createDto.getCompanyId())
        ) < 1) {
            throw new NoSuchDataException("不存在此物业公司");
        }

        // 检查此部门是否已经新增
        if (departmentDAO.selectCount(
                new QueryWrapper<DepartmentEntity>()
                        .lambda()
                        .eq(DepartmentEntity::getCompanyId, createDto.getCompanyId())
                        .eq(DepartmentEntity::getDepartmentName, createDto.getDepartmentName())
        ) >= 1) {
            throw new DataAlreadyExistsException("此部门已经存在");
        }

        // 执行新增
        departmentDAO.insert(departmentTransformer.createDtoToEntity(createDto));
        return Boolean.TRUE;
    }

    @Override
    public DepartmentDTO findDepartmentById(Integer departmentId) {
        DepartmentEntity departmentEntity = departmentDAO.selectById(departmentId);
        if (departmentEntity == null) {
            throw new NoSuchDataException("不存在此部门");
        }

        return departmentTransformer.entityToDto(
                // 输送部门信息
                departmentEntity,
                // 取出关联的员工，并取出员工信息
                workerDAO.selectList(new QueryWrapper<WorkerEntity>().lambda()
                        .eq(WorkerEntity::getDepartmentId, departmentId))
                        .stream()
                        .map(worker -> workerTransformer.toDto(
                                worker,
                                userDAO.selectById(worker.getWorkerId()),
                                departmentEntity)
                        )
                        .collect(Collectors.toList()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addWorker(WorkerHireDTO hireDto) {
        // 检查是否没有此用户
        if (userDAO.selectCount(new QueryWrapper<UserEntity>().lambda().eq(Entity::getId, hireDto.getWorkerId())) == 0) {
            throw new NoSuchDataException("系统中不存在此用户，请先注册");
        }
        // 检查是否重复添加
        if (workerDAO.selectCount(
                new QueryWrapper<WorkerEntity>()
                        .lambda()
                        .eq(WorkerEntity::getWorkerId, hireDto.getWorkerId())
                        .eq(WorkerEntity::getDepartmentId, hireDto.getDepartmentId())) >= 1) {
            throw new DataSaveException("已添加过此员工");
        }
        // 执行添加
        workerDAO.insert(workerTransformer.hireDtoToEntity(hireDto));
        return Boolean.TRUE;
    }

    @Override
    public WorkerDTO findWorker(Integer workerId) {
        // 查询员工信息
        WorkerEntity workerEntity = workerDAO.selectOne(
                new QueryWrapper<WorkerEntity>().lambda().eq(WorkerEntity::getWorkerId, workerId)
        );

        return workerTransformer.toDto(
                // 如果不存在则抛出异常
                Optional.ofNullable(workerEntity).orElseThrow(() -> new NoSuchDataException("不存在此员工")),
                userDAO.selectById(workerEntity.getWorkerId()),
                departmentDAO.selectById(workerEntity.getDepartmentId())
        );
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean removeWorker(WorkerFireDTO fireDto) {
        LambdaQueryWrapper<WorkerEntity> target = new QueryWrapper<WorkerEntity>()
                .lambda()
                .eq(WorkerEntity::getWorkerId, fireDto.getWorkerId())
                .eq(WorkerEntity::getDepartmentId, fireDto.getDepartmentId());
        // 如果不存在此员工，直接返回
        if (workerDAO.selectCount(target) != 1) {
            throw new NoSuchDataException("不存在此员工");
        }

        // 执行删除
        workerDAO.delete(target);
        return Boolean.TRUE;
    }

    @Override
    public Boolean removeDepartmentById(Integer departmentId) {
        // 对公司执行逻辑删除
        departmentDAO.deleteById(departmentId);

        // 创建查询条件
        // 部门查询条件
        LambdaQueryWrapper<DepartmentEntity> departmentQuery =
                new QueryWrapper<DepartmentEntity>().lambda().eq(Entity::getId, departmentId);

        // 员工查询条件
        LambdaQueryWrapper<WorkerEntity> workerQuery =
                new QueryWrapper<WorkerEntity>().lambda().eq(WorkerEntity::getDepartmentId, departmentId);

        // 对部门执行逻辑删除
        workerDAO.delete(workerQuery);

        // 查询删除结果
        if (departmentDAO.selectCount(departmentQuery) != 0 || workerDAO.selectCount(workerQuery) != 0) {
            throw new FailOperationException();
        }
        return Boolean.TRUE;
    }
}
